package cn.cyh.queue_service.service.impl;

import cn.cyh.queue_service.service.CacheService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.stereotype.Service;

import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * 缓存服务实现类，基于Redis
 * 整合GeneralCacheServiceImpl和RedisCacheServiceImpl
 */
@Service
@Slf4j
@RequiredArgsConstructor
public class CacheServiceImpl implements CacheService {

    private final RedisTemplate<String, Object> redisTemplate;

    private static final String RELEASE_LOCK_SCRIPT = 
            "if redis.call('get', KEYS[1]) == ARGV[1] then " +
            "    return redis.call('del', KEYS[1]) " +
            "else " +
            "    return 0 " +
            "end";

    @Override
    public void set(String key, Object value) {
        try {
            redisTemplate.opsForValue().set(key, value);
        } catch (Exception e) {
            log.error("缓存设置异常: key={}", key, e);
            throw new RuntimeException("缓存设置异常", e);
        }
    }

    @Override
    public void set(String key, Object value, long timeout, TimeUnit unit) {
        try {
            redisTemplate.opsForValue().set(key, value, timeout, unit);
        } catch (Exception e) {
            log.error("缓存设置异常: key={}, timeout={}, unit={}", key, timeout, unit, e);
            throw new RuntimeException("缓存设置异常", e);
        }
    }

    @Override
    @SuppressWarnings("unchecked")
    public <T> T get(String key) {
        try {
            return (T) redisTemplate.opsForValue().get(key);
        } catch (Exception e) {
            log.error("缓存获取异常: key={}", key, e);
            throw new RuntimeException("缓存获取异常", e);
        }
    }

    @Override
    public boolean delete(String key) {
        try {
            return Boolean.TRUE.equals(redisTemplate.delete(key));
        } catch (Exception e) {
            log.error("缓存删除异常: key={}", key, e);
            throw new RuntimeException("缓存删除异常", e);
        }
    }

    @Override
    public long delete(Collection<String> keys) {
        try {
            Long count = redisTemplate.delete(keys);
            return count != null ? count : 0;
        } catch (Exception e) {
            log.error("批量缓存删除异常: keys={}", keys, e);
            throw new RuntimeException("批量缓存删除异常", e);
        }
    }

    @Override
    public boolean expire(String key, long timeout, TimeUnit unit) {
        try {
            return Boolean.TRUE.equals(redisTemplate.expire(key, timeout, unit));
        } catch (Exception e) {
            log.error("设置过期时间异常: key={}, timeout={}, unit={}", key, timeout, unit, e);
            throw new RuntimeException("设置过期时间异常", e);
        }
    }

    @Override
    public boolean hasKey(String key) {
        try {
            return Boolean.TRUE.equals(redisTemplate.hasKey(key));
        } catch (Exception e) {
            log.error("判断键是否存在异常: key={}", key, e);
            throw new RuntimeException("判断键是否存在异常", e);
        }
    }

    @Override
    public long getExpire(String key, TimeUnit unit) {
        try {
            Long expire = redisTemplate.getExpire(key, unit);
            return expire != null ? expire : -1;
        } catch (Exception e) {
            log.error("获取过期时间异常: key={}, unit={}", key, unit, e);
            throw new RuntimeException("获取过期时间异常", e);
        }
    }

    @Override
    public long increment(String key, long delta) {
        try {
            Long increment = redisTemplate.opsForValue().increment(key, delta);
            return increment != null ? increment : 0;
        } catch (Exception e) {
            log.error("递增操作异常: key={}, delta={}", key, delta, e);
            throw new RuntimeException("递增操作异常", e);
        }
    }

    @Override
    public long decrement(String key, long delta) {
        try {
            Long decrement = redisTemplate.opsForValue().decrement(key, delta);
            return decrement != null ? decrement : 0;
        } catch (Exception e) {
            log.error("递减操作异常: key={}, delta={}", key, delta, e);
            throw new RuntimeException("递减操作异常", e);
        }
    }

    @Override
    public Set<String> keys(String pattern) {
        try {
            return redisTemplate.keys(pattern);
        } catch (Exception e) {
            log.error("获取匹配的键异常: pattern={}", pattern, e);
            throw new RuntimeException("获取匹配的键异常", e);
        }
    }

    @Override
    public long leftPush(String key, Object value) {
        try {
            Long size = redisTemplate.opsForList().leftPush(key, value);
            return size != null ? size : 0;
        } catch (Exception e) {
            log.error("列表左推入异常: key={}", key, e);
            throw new RuntimeException("列表左推入异常", e);
        }
    }

    @Override
    public long rightPush(String key, Object value) {
        try {
            Long size = redisTemplate.opsForList().rightPush(key, value);
            return size != null ? size : 0;
        } catch (Exception e) {
            log.error("列表右推入异常: key={}", key, e);
            throw new RuntimeException("列表右推入异常", e);
        }
    }

    @Override
    @SuppressWarnings("unchecked")
    public <T> T leftPop(String key) {
        try {
            return (T) redisTemplate.opsForList().leftPop(key);
        } catch (Exception e) {
            log.error("列表左弹出异常: key={}", key, e);
            throw new RuntimeException("列表左弹出异常", e);
        }
    }

    @Override
    @SuppressWarnings("unchecked")
    public <T> T rightPop(String key) {
        try {
            return (T) redisTemplate.opsForList().rightPop(key);
        } catch (Exception e) {
            log.error("列表右弹出异常: key={}", key, e);
            throw new RuntimeException("列表右弹出异常", e);
        }
    }

    @Override
    public long listSize(String key) {
        try {
            Long size = redisTemplate.opsForList().size(key);
            return size != null ? size : 0;
        } catch (Exception e) {
            log.error("获取列表长度异常: key={}", key, e);
            throw new RuntimeException("获取列表长度异常", e);
        }
    }

    @Override
    @SuppressWarnings("unchecked")
    public <T> List<T> listRange(String key, long start, long end) {
        try {
            return (List<T>) redisTemplate.opsForList().range(key, start, end);
        } catch (Exception e) {
            log.error("获取列表范围异常: key={}, start={}, end={}", key, start, end, e);
            throw new RuntimeException("获取列表范围异常", e);
        }
    }

    @Override
    public boolean tryLock(String lockKey, String requestId, long expireTime, TimeUnit timeUnit) {
        try {
            Boolean success = redisTemplate.opsForValue().setIfAbsent(lockKey, requestId, expireTime, timeUnit);
            return Boolean.TRUE.equals(success);
        } catch (Exception e) {
            log.error("获取分布式锁异常: lockKey={}, requestId={}, expireTime={}", lockKey, requestId, expireTime, e);
            throw new RuntimeException("获取分布式锁异常", e);
        }
    }

    @Override
    public boolean releaseLock(String lockKey, String requestId) {
        try {
            DefaultRedisScript<Long> redisScript = new DefaultRedisScript<>();
            redisScript.setScriptText(RELEASE_LOCK_SCRIPT);
            redisScript.setResultType(Long.class);
            Long result = redisTemplate.execute(redisScript, Collections.singletonList(lockKey), requestId);
            return result != null && result == 1;
        } catch (Exception e) {
            log.error("释放分布式锁异常: lockKey={}, requestId={}", lockKey, requestId, e);
            throw new RuntimeException("释放分布式锁异常", e);
        }
    }

    @Override
    public void hashSet(String key, String hashKey, Object value) {
        try {
            redisTemplate.opsForHash().put(key, hashKey, value);
        } catch (Exception e) {
            log.error("哈希设置异常: key={}, hashKey={}", key, hashKey, e);
            throw new RuntimeException("哈希设置异常", e);
        }
    }

    @Override
    @SuppressWarnings("unchecked")
    public <T> T hashGet(String key, String hashKey) {
        try {
            return (T) redisTemplate.opsForHash().get(key, hashKey);
        } catch (Exception e) {
            log.error("哈希获取异常: key={}, hashKey={}", key, hashKey, e);
            throw new RuntimeException("哈希获取异常", e);
        }
    }

    @Override
    public long hashDelete(String key, Object... hashKeys) {
        try {
            Long count = redisTemplate.opsForHash().delete(key, hashKeys);
            return count != null ? count : 0;
        } catch (Exception e) {
            log.error("哈希删除异常: key={}, hashKeys={}", key, hashKeys, e);
            throw new RuntimeException("哈希删除异常", e);
        }
    }

    @Override
    public boolean hashHasKey(String key, String hashKey) {
        try {
            return Boolean.TRUE.equals(redisTemplate.opsForHash().hasKey(key, hashKey));
        } catch (Exception e) {
            log.error("判断哈希字段是否存在异常: key={}, hashKey={}", key, hashKey, e);
            throw new RuntimeException("判断哈希字段是否存在异常", e);
        }
    }

    @Override
    public Map<Object, Object> hashEntries(String key) {
        try {
            return redisTemplate.opsForHash().entries(key);
        } catch (Exception e) {
            log.error("获取哈希所有字段异常: key={}", key, e);
            throw new RuntimeException("获取哈希所有字段异常", e);
        }
    }
} 